package com.yuelao.yuelao_backend.controller;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.yuelao.yuelao_backend.common.ApiResponse;
import com.yuelao.yuelao_backend.common.BizException;
import com.yuelao.yuelao_backend.common.ErrorCode;
import com.yuelao.yuelao_backend.entity.User;
import com.yuelao.yuelao_backend.dto.NotificationSettingsDTO;
import com.yuelao.yuelao_backend.dto.PrivacySettingsDTO;
import com.yuelao.yuelao_backend.entity.UserBlacklist;
import com.yuelao.yuelao_backend.entity.UserSettings;
import com.yuelao.yuelao_backend.mapper.UserBlacklistMapper;
import com.yuelao.yuelao_backend.mapper.UserMapper;
import com.yuelao.yuelao_backend.mapper.UserSettingsMapper;
import com.yuelao.yuelao_backend.service.VerificationCodeService;
import com.yuelao.yuelao_backend.util.UserContextUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import jakarta.validation.Valid;
import jakarta.validation.constraints.NotBlank;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 设置Controller
 */
@RestController
@RequestMapping("/settings")
@Slf4j
@RequiredArgsConstructor
public class SettingsController {

    private final UserSettingsMapper userSettingsMapper;
    private final UserBlacklistMapper userBlacklistMapper;
    private final UserMapper userMapper;
    private final VerificationCodeService verificationCodeService;
    private final PasswordEncoder passwordEncoder;

    /**
     * 获取用户设置
     * GET /settings
     * @return 用户设置
     */
    @GetMapping
    public ApiResponse<UserSettings> getSettings() {
        Long userId = UserContextUtil.getCurrentUserId();
        
        LambdaQueryWrapper<UserSettings> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserSettings::getUserId, userId);
        UserSettings settings = userSettingsMapper.selectOne(wrapper);
        
        if (settings == null) {
            // 初始化默认设置
            settings = new UserSettings();
            settings.setUserId(userId);
            settings.setCreatedAt(LocalDateTime.now());
            settings.setUpdatedAt(LocalDateTime.now());
            userSettingsMapper.insert(settings);
        }
        
        return ApiResponse.ok(settings);
    }

    /**
     * 更新通知设置
     * PUT /settings/notifications
     * @param notifications 通知设置
     * @return 是否成功
     */
    @PutMapping("/notifications")
    @Transactional(rollbackFor = Exception.class)
    public ApiResponse<Boolean> updateNotifications(@RequestBody NotificationSettingsDTO notifications) {
        Long userId = UserContextUtil.getCurrentUserId();
        
        LambdaQueryWrapper<UserSettings> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserSettings::getUserId, userId);
        UserSettings settings = userSettingsMapper.selectOne(wrapper);
        
        if (settings == null) {
            settings = new UserSettings();
            settings.setUserId(userId);
            settings.setCreatedAt(LocalDateTime.now());
        }
        
        if (notifications != null) {
            settings.setNotificationLike(notifications.getLike());
            settings.setNotificationMatch(notifications.getMatch());
            settings.setNotificationMessage(notifications.getMessage());
            settings.setNotificationComment(notifications.getComment());
            settings.setNotificationSystem(notifications.getSystem());
        }
        settings.setUpdatedAt(LocalDateTime.now());
        
        if (settings.getId() == null) {
            userSettingsMapper.insert(settings);
        } else {
            userSettingsMapper.updateById(settings);
        }
        
        return ApiResponse.ok(true);
    }

    /**
     * 更新隐私设置
     * PUT /settings/privacy
     * @param privacy 隐私设置
     * @return 是否成功
     */
    @PutMapping("/privacy")
    @Transactional(rollbackFor = Exception.class)
    public ApiResponse<Boolean> updatePrivacy(@RequestBody PrivacySettingsDTO privacy) {
        Long userId = UserContextUtil.getCurrentUserId();
        
        LambdaQueryWrapper<UserSettings> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserSettings::getUserId, userId);
        UserSettings settings = userSettingsMapper.selectOne(wrapper);
        
        if (settings == null) {
            settings = new UserSettings();
            settings.setUserId(userId);
            settings.setCreatedAt(LocalDateTime.now());
        }
        
        if (privacy != null) {
            settings.setPrivacyShowAge(privacy.getShowAge());
            settings.setPrivacyShowLocation(privacy.getShowLocation());
            settings.setPrivacyShowOnline(privacy.getShowOnline());
            settings.setPrivacyAllowVisitor(privacy.getAllowVisitor());
            settings.setPrivacyAllowStrangerMessage(privacy.getAllowStrangerMessage());
        }
        settings.setUpdatedAt(LocalDateTime.now());
        
        if (settings.getId() == null) {
            userSettingsMapper.insert(settings);
        } else {
            userSettingsMapper.updateById(settings);
        }
        
        return ApiResponse.ok(true);
    }

    /**
     * 修改手机号
     * PUT /settings/change-phone
     * @param request 修改手机号请求
     * @return 是否成功
     */
    @PutMapping("/change-phone")
    @Transactional(rollbackFor = Exception.class)
    public ApiResponse<Boolean> changePhone(@Valid @RequestBody ChangePhoneRequest request) {
        Long userId = UserContextUtil.getCurrentUserId();
        
        // 验证验证码
        boolean isValid = verificationCodeService.verifyCode(
            request.getNewPhone(),
            request.getCode(),
            "change_phone"
        );
        
        if (!isValid) {
            throw new BizException(ErrorCode.PARAMS_ERROR, "验证码无效或已过期");
        }
        
        // 检查新手机号是否已被使用
        LambdaQueryWrapper<User> phoneWrapper = new LambdaQueryWrapper<>();
        phoneWrapper.eq(User::getPhone, request.getNewPhone());
        User existingUser = userMapper.selectOne(phoneWrapper);
        
        if (existingUser != null && !existingUser.getId().equals(userId)) {
            throw new BizException(ErrorCode.OPERATION_ERROR, "该手机号已被其他用户使用");
        }
        
        // 更新手机号
        User user = userMapper.selectById(userId);
        user.setPhone(request.getNewPhone());
        userMapper.updateById(user);
        
        return ApiResponse.ok(true, "手机号修改成功");
    }

    /**
     * 修改密码
     * PUT /settings/change-password
     * @param request 修改密码请求
     * @return 是否成功
     */
    @PutMapping("/change-password")
    @Transactional(rollbackFor = Exception.class)
    public ApiResponse<Boolean> changePassword(@Valid @RequestBody ChangePasswordRequest request) {
        Long userId = UserContextUtil.getCurrentUserId();
        
        User user = userMapper.selectById(userId);
        
        // 验证旧密码
        if (!passwordEncoder.matches(request.getOldPassword(), user.getPassword())) {
            throw new BizException(ErrorCode.PARAMS_ERROR, "旧密码不正确");
        }
        
        // 更新密码
        user.setPassword(passwordEncoder.encode(request.getNewPassword()));
        userMapper.updateById(user);
        
        return ApiResponse.ok(true, "密码修改成功");
    }

    /**
     * 获取黑名单
     * GET /settings/block-list
     * @return 黑名单列表
     */
    @GetMapping("/block-list")
    public ApiResponse<List<Map<String, Object>>> getBlockList() {
        Long userId = UserContextUtil.getCurrentUserId();
        
        LambdaQueryWrapper<UserBlacklist> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserBlacklist::getUserId, userId)
               .orderByDesc(UserBlacklist::getCreatedAt);
        List<UserBlacklist> blacklist = userBlacklistMapper.selectList(wrapper);
        
        List<Map<String, Object>> result = blacklist.stream()
            .map(item -> {
                Map<String, Object> map = new HashMap<>();
                User blockedUser = userMapper.selectById(item.getBlockedUserId());
                if (blockedUser != null) {
                    map.put("id", blockedUser.getId());
                    map.put("nickname", blockedUser.getNickname());
                    map.put("avatar", blockedUser.getAvatar());
                    map.put("blocked_at", item.getCreatedAt());
                }
                return map;
            })
            .collect(Collectors.toList());
        
        return ApiResponse.ok(result);
    }

    /**
     * 拉黑用户
     * POST /settings/block/{userId}
     * @param targetUserId 目标用户ID
     * @return 是否成功
     */
    @PostMapping("/block/{userId}")
    @Transactional(rollbackFor = Exception.class)
    public ApiResponse<Boolean> blockUser(@PathVariable("userId") Long targetUserId) {
        Long userId = UserContextUtil.getCurrentUserId();
        
        // 检查是否已拉黑
        LambdaQueryWrapper<UserBlacklist> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserBlacklist::getUserId, userId)
               .eq(UserBlacklist::getBlockedUserId, targetUserId);
        UserBlacklist existing = userBlacklistMapper.selectOne(wrapper);
        
        if (existing != null) {
            return ApiResponse.ok(true, "该用户已在黑名单中");
        }
        
        UserBlacklist blacklist = new UserBlacklist();
        blacklist.setUserId(userId);
        blacklist.setBlockedUserId(targetUserId);
        blacklist.setCreatedAt(LocalDateTime.now());
        userBlacklistMapper.insert(blacklist);
        
        return ApiResponse.ok(true, "已将该用户加入黑名单");
    }

    /**
     * 解除拉黑
     * DELETE /settings/unblock/{userId}
     * @param targetUserId 目标用户ID
     * @return 是否成功
     */
    @DeleteMapping("/unblock/{userId}")
    @Transactional(rollbackFor = Exception.class)
    public ApiResponse<Boolean> unblockUser(@PathVariable("userId") Long targetUserId) {
        Long userId = UserContextUtil.getCurrentUserId();
        
        LambdaQueryWrapper<UserBlacklist> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserBlacklist::getUserId, userId)
               .eq(UserBlacklist::getBlockedUserId, targetUserId);
        userBlacklistMapper.delete(wrapper);
        
        return ApiResponse.ok(true, "已将该用户移出黑名单");
    }

    /**
     * 绑定/更新社交账号
     * PUT /settings/social/{type}
     * @param type 社交账号类型: wechat/qq
     * @param request 绑定请求
     * @return 是否成功
     */
    @PutMapping("/social/{type}")
    @Transactional(rollbackFor = Exception.class)
    public ApiResponse<Boolean> bindSocialAccount(
            @PathVariable String type,
            @RequestBody Map<String, String> request) {
        Long userId = UserContextUtil.getCurrentUserId();
        
        User user = userMapper.selectById(userId);
        if (user == null) {
            throw new BizException(ErrorCode.NOT_FOUND_ERROR, "用户不存在");
        }
        
        String account = request.get("account");
        if (StrUtil.isBlank(account)) {
            throw new BizException(ErrorCode.PARAMS_ERROR, "账号不能为空");
        }
        
        switch (type.toLowerCase()) {
            case "wechat":
                user.setWechat(account);
                break;
            case "qq":
                user.setQq(account);
                break;
            default:
                throw new BizException(ErrorCode.PARAMS_ERROR, "不支持的社交账号类型");
        }
        
        userMapper.updateById(user);
        return ApiResponse.ok(true, "社交账号绑定成功");
    }

    /**
     * 注销账号
     * DELETE /settings/delete-account
     * @param request 注销请求
     * @return 是否成功
     */
    @DeleteMapping("/delete-account")
    @Transactional(rollbackFor = Exception.class)
    public ApiResponse<Boolean> deleteAccount(@Valid @RequestBody DeleteAccountRequest request) {
        Long userId = UserContextUtil.getCurrentUserId();
        
        User user = userMapper.selectById(userId);
        if (user == null) {
            throw new BizException(ErrorCode.NOT_FOUND_ERROR, "用户不存在");
        }
        
        // 1. 验证密码
        if (!passwordEncoder.matches(request.getPassword(), user.getPassword())) {
            throw new BizException(ErrorCode.PARAMS_ERROR, "密码不正确");
        }
        
        // 2. 验证验证码（可选，增强安全性）
        if (StrUtil.isNotBlank(request.getCode())) {
            boolean isValid = verificationCodeService.verifyCode(
                user.getPhone(),
                request.getCode(),
                "delete_account"
            );
            if (!isValid) {
                throw new BizException(ErrorCode.PARAMS_ERROR, "验证码无效或已过期");
            }
        }
        
        // 3. 软删除用户（将状态设为禁用，而不是真正删除数据）
        // 注意：根据数据库设计，外键不使用级联删除，所以这里只修改状态
        user.setStatus(0); // 0-禁用
        userMapper.updateById(user);
        
        // 4. TODO: 根据业务需求，可能需要：
        // - 清除用户的个人信息
        // - 删除用户的关注/粉丝关系
        // - 删除用户的消息记录
        // - 删除用户的帖子和评论
        // - 等等...
        
        return ApiResponse.ok(true, "账号注销成功");
    }

    /**
     * 清理缓存
     * POST /settings/clear-cache
     * @return 清理结果
     */
    @PostMapping("/clear-cache")
    public ApiResponse<Void> clearCache() {
        Long userId = UserContextUtil.getCurrentUserId();
        
        // TODO: 实现清理用户相关缓存逻辑
        // 这是一个客户端操作接口，主要用于：
        // 1. 清理用户浏览历史缓存
        // 2. 清理图片缓存
        // 3. 重置某些临时设置
        // 服务端可以记录清理操作日志，但主要清理工作由客户端完成
        
        log.info("用户 {} 请求清理缓存", userId);
        
        // 记录操作日志（可选）
        // userActionLogService.recordAction(userId, "CLEAR_CACHE", null);
        
        return ApiResponse.ok(null, "缓存清理请求已处理");
    }

    /**
     * 修改手机号请求DTO
     */
    @lombok.Data
    public static class ChangePhoneRequest {
        @NotBlank(message = "新手机号不能为空")
        private String newPhone;
        
        @NotBlank(message = "验证码不能为空")
        private String code;
    }

    /**
     * 修改密码请求DTO
     */
    @lombok.Data
    public static class ChangePasswordRequest {
        @NotBlank(message = "旧密码不能为空")
        private String oldPassword;
        
        @NotBlank(message = "新密码不能为空")
        private String newPassword;
    }

    /**
     * 注销账号请求DTO
     */
    @lombok.Data
    public static class DeleteAccountRequest {
        @NotBlank(message = "密码不能为空")
        private String password;
        
        private String code; // 验证码（可选）
        
        private String reason; // 注销原因（可选）
    }
}

